/**
 * Copyright (C) 2012 The SkyTvOS Project
 * <p/>
 * Version     Date           Author
 * ─────────────────────────────────────
 * 2014年12月25日         cassie
 */

package com.coocaa.launcher.pattern.normal.hotseat;

import android.animation.ObjectAnimator;
import android.animation.PropertyValuesHolder;
import android.app.Activity;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Rect;
import android.graphics.drawable.BitmapDrawable;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.util.Log;
import android.util.SparseArray;
import android.view.Gravity;
import android.view.KeyEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.AlphaAnimation;
import android.view.animation.Animation;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;

import com.coocaa.launcher.framework.launcherhost.view.AppItemView;
import com.coocaa.launcher.framework.manager.configdata.data.LauncherAppItemTableData.AppItemData;
import com.coocaa.launcher.pattern.normal.NormalController;
import com.coocaa.launcher.pattern.normal.NormalController.BoundaryDetector;
import com.coocaa.launcher.pattern.normal.NormalController.HotSeatExecutor;
import com.coocaa.launcher.pattern.normal.UIConfig;
import com.coocaa.launcher.pattern.normal.guide.GuideTips;
import com.coocaa.launcher.pattern.normal.guide.GuideView.GuideViewManager;
import com.coocaa.launcher.pattern.normal.guide.IGuideView.Tip;
import com.coocaa.launcher.pattern.normal.item.AppEditView;
import com.coocaa.launcher.pattern.normal.item.TempAddView;
import com.coocaa.launcher.pattern.normal.pick.PickResultListener;
import com.coocaa.launcher.pattern.normal.util.ItemViewFactory;
import com.coocaa.launcher.pattern.normal.util.LayoutExtra;
import com.coocaa.launcher.util.FrescoBitmapFactory;
import com.coocaa.launcher.util.PathConstants;
import com.coocaa.launcher.wallpaper.WallpaperManager;
import com.coocaa.x.framework.app.CoocaaApplication;
import com.coocaa.x.framework.data.JObject;
import com.coocaa.x.framework.utils.FastBlur;
import com.coocaa.x.framework.utils.ImageUtils;
import com.coocaa.x.framework.utils.LiteHandlerThread;
import com.coocaa.x.framework.utils.LogUtils;
import com.coocaa.x.uipackage.BaseView;
import com.coocaa.x.uipackage.SkinManager;
import com.skyworth.logsdk.appstore.LogAPIForAppStore;
import com.tianci.appstore.R;
import com.tianci.appstore.ui.widget.CatchImageView;
import com.tianci.appstore.utils.SkyConstants;

import java.util.ArrayList;
import java.util.List;

public class HotSeatView extends BaseView implements WallpaperManager.OnBackgroundChangeListener {
    private Context mContext;
    private FrameLayout mainLayout;
    private List<HotSeatLine> layoutList;
    private int itemCount = 0;
    private int focusLineIndex;

    private AppEditView editBtn;
    private TextView tipText;
    private FocusView focusImage;
    private ImageView pageNoImage;
    private boolean doFocusAnim = true;
    private BitmapDrawable smallBg = null;
    private BitmapDrawable bigBg = null;

    private BitmapDrawable tempSmall = null;
    private BitmapDrawable tempBig = null;

    private static int maxCount = UIConfig.HotSeatItemCountPerPage * UIConfig.HotSeatMaxPageCount;
    private static final int enterEditDuration = 500;

    private HotSeatState currentState = HotSeatState.NORMAL;
    private int selectedResId = R.drawable.hot_seat_focus_bg;

    private View lastFocusView = null;

    public static boolean handleItemKey = true;

    @Override
    public void onBackgroundChange() {
        beginChangeBackground();
    }

    private void beginChangeBackground(){
        AlphaAnimation animation = new AlphaAnimation(1.0f,0f);
        animation.setDuration(2000);
        animation.setAnimationListener(new Animation.AnimationListener() {
            @Override
            public void onAnimationStart(Animation animation) {

            }

            @Override
            public void onAnimationEnd(Animation animation) {

            }

            @Override
            public void onAnimationRepeat(Animation animation) {
                initBg();
            }
        });
        animation.setRepeatCount(1);
        animation.setRepeatMode(Animation.REVERSE);
        startAnimation(animation);
    }

    FrescoBitmapFactory.OnBitmapLoadListener bigListener = new FrescoBitmapFactory.OnBitmapLoadListener() {
        @Override
        public void loadSuccess(Bitmap bitmap, String url) {
            tempBig = bigBg;
            bigBg = new BitmapDrawable(ImageUtils.changeBitmapBrightness(FastBlur.doBlur(Bitmap.createBitmap(
                            bitmap, 0, 102, 384, 114), 16, true
            ), 0.7f, 0));
            recycleBitmapDrawable(tempBig);
        }

        @Override
        public void loadFailed(String url) {
            WallpaperManager.getInstance().getResourceBitmap(R.drawable.bg_1, 384, 216, bigListener);
        }
    };

    FrescoBitmapFactory.OnBitmapLoadListener smallListener = new FrescoBitmapFactory.OnBitmapLoadListener() {
        @Override
        public void loadSuccess(Bitmap bitmap, String url) {
            tempSmall = smallBg;
            smallBg = new BitmapDrawable(ImageUtils.changeBitmapBrightness(FastBlur.doBlur(Bitmap.createBitmap(
                            bitmap, 0, 159, 384, 57), 16, true
            ), 0.7f, 0));
            runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    setBackgroundDrawable(smallBg);
                    recycleBitmapDrawable(tempSmall);
                }
            });
        }

        @Override
        public void loadFailed(String url) {
            WallpaperManager.getInstance().getResourceBitmap(R.drawable.bg_1, 384, 216, smallListener);
        }
    };

    public enum HotSeatState {
        NORMAL, EDIT, HIDE
    }

    ;

    public HotSeatView(Context context) {
        super(context);
        this.mContext = context;
        this.setClickable(false);
        this.setFocusableInTouchMode(false);
        //this.setBackgroundColor(SkinManager.getInstance().getColor(R.color.hot_seat_bg_color));
        // TODO Auto-generated constructor stub

        createView();

        showHotSeatTips();
        initBg();
        WallpaperManager.getInstance().addBackgroundChangeListener(this);

    }


    private void initBg() {
        WallpaperManager.getInstance().getBackground(R.drawable.bg_1, 384, 216, smallListener);
        WallpaperManager.getInstance().getBackground(R.drawable.bg_1, 384, 216, bigListener);
    }


    private void createView() {
        mainLayout = new FrameLayout(mContext);
        mainLayout.setPadding(UIConfig.hotSeatLeftSpacing, 0, UIConfig.hotSeatLeftSpacing, 0);
        this.addView(mainLayout, new LayoutParams(LayoutParams.MATCH_PARENT,
                UIConfig.hotSeatLineHeight * UIConfig.HotSeatMaxPageCount, Gravity.TOP));

        layoutList = new ArrayList<HotSeatLine>();
        for (int i = 0; i < UIConfig.HotSeatMaxPageCount; i++) {
            HotSeatLine view = new HotSeatLine(mContext, i, childFocusListener);
            layoutList.add(view);
            if (i == 0) {
                mainLayout.addView(view);
            } else {
                mainLayout.addView(view);
            }
            LayoutParams params = new LayoutParams(LayoutParams.MATCH_PARENT,
                    UIConfig.hotSeatLineHeight);
            params.topMargin = i * UIConfig.hotSeatLineHeight;
            view.setLayoutParams(params);
            view.setChildClickListener(childClickListener);
            view.setHotSeatExecutor(hotSeatExecutor);
        }

        createTipLayout();
        focusImage = new FocusView(mContext);
        this.addView(focusImage, new LayoutParams(LayoutParams.WRAP_CONTENT,
                LayoutParams.WRAP_CONTENT, Gravity.LEFT));
        SkinManager.getInstance().setBackgroundResource(focusImage, selectedResId);
        createPageNoView();
    }

    private void createTipLayout() {
        editBtn = createEditAddView();
        editBtn.setOnKeyListener(new OnKeyListener() {
            @Override
            public boolean onKey(View v, int keyCode, KeyEvent event) {
                // TODO Auto-generated method stub
                if (!handleItemKey)
                    LogUtils.d("key", "edit btn onkey, keycode = " + keyCode
                            + ", handleItemKey = false");
                return !handleItemKey;
            }
        });
        tipText = new TextView(mContext);
        tipText.setTextSize(SkyConstants.Dpi(35));
        tipText.setText(R.string.no_hot_items_yet);
        tipText.setGravity(Gravity.CENTER_VERTICAL);
        tipText.setAlpha(0);

        LayoutParams editAddParams = new LayoutParams(editAddSize, editAddSize);
        editAddParams.leftMargin = editLeftPadding;
        editAddParams.topMargin = (UIConfig.hotSeatLineHeight - editAddSize) / 2;
        this.addView(editBtn, editAddParams);

        LayoutParams tipTextParams = new LayoutParams(LayoutParams.MATCH_PARENT, editAddSize,
                Gravity.CENTER_VERTICAL | Gravity.LEFT);
        tipTextParams.leftMargin = UIConfig.hotSeatLeftSpacing;
        this.addView(tipText, tipTextParams);
    }

    private void resetEditTipStatus() {
        if (currentState == HotSeatState.EDIT)
            return;
        LogUtils.d("add_item", "reset Edit Tip, itemCount = " + itemCount);
        if (itemCount > 0) {
            editBtn.setEditState();
            if (tipText.getAlpha() != 0) {
                if (tipText.animate() != null)
                    tipText.animate().cancel();
                tipText.animate().alpha(0).setDuration(enterEditDuration);
            }
        } else {
            editBtn.setAddState();
            if (tipText.getAlpha() != 1) {
                if (tipText.animate() != null)
                    tipText.animate().cancel();
                tipText.animate().alpha(1).setDuration(enterEditDuration);
            }
        }
    }

    private int pageNoMargin = SkyConstants.Div(5);
    private int scrollHeight;

    public HotSeatState getCurrentState() {
        return currentState;
    }

    public void setCurrentState(HotSeatState currentState) {
        this.currentState = currentState;
    }

    private void createPageNoView() {
        pageNoImage = new CatchImageView(mContext);
        SkinManager.getInstance().setBackgroundResource(pageNoImage, R.drawable.gridview_scroll);
        scrollHeight = (UIConfig.hotSeatLineHeight - pageNoMargin * 2)
                / UIConfig.HotSeatMaxPageCount;
        FrameLayout.LayoutParams scrollParams = new LayoutParams(LayoutParams.WRAP_CONTENT,
                scrollHeight, Gravity.RIGHT);
        scrollParams.topMargin = pageNoMargin;
        scrollParams.rightMargin = pageNoMargin / 3;
        this.addView(pageNoImage, scrollParams);
    }

    private void resetPageScroll() {
        if (pageNoImage.animate() != null)
            pageNoImage.animate().cancel();
        if (currentState != HotSeatState.EDIT) {
            pageNoImage.animate().y(pageNoMargin + focusLineIndex * scrollHeight).setDuration(100);
        }
    }

    @Override
    public void onThemeChange() {
        // TODO Auto-generated method stub
        SkinManager.getInstance().setBackgroundColor(focusImage, selectedResId);
        if (downArrowImage != null)
            SkinManager.getInstance().setBackgroundResource(downArrowImage,
                    R.drawable.hot_seat_down_arrow);
    }

    private int editAddSize = UIConfig.hotSeatItemWidth;
    private int editLeftPadding = SkyConstants.Div(51);

    // 创建一个按钮：点击进入编辑状态
    private AppEditView createEditAddView() {
        AppEditView addView = new AppEditView(mContext);
        addView.setTag("add");
        addView.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                // TODO Auto-generated method stub
                if (currentState == HotSeatState.NORMAL)
                    enterEditState();
                else if (currentState == HotSeatState.EDIT)
                    exitEditState();
                v.invalidate();
            }
        });
        addView.setOnFocusChangeListener(addEditFocusListener);
        return addView;
    }

    private ANIM_TYPE animType;

    public enum ANIM_TYPE {
        NONE, EXPAND, SHRINK, MOVE_PREV, MOVE_NEXT,
    }

    ;

    private int stepCount = 10; // 步数，跟动画速度相关，越大越慢，越小越快
    private int stepHeight;
    private int destHeight;
    private int destY;
    private int stepY;

    // 进入编辑状态
    private void enterEditState() {
        if (bigBg != null)
            setBackgroundDrawable(bigBg);

        for (int i = 0; i < mainLayout.getChildCount(); i++) {
            HotSeatLine lineView = (HotSeatLine) mainLayout.getChildAt(i);
            lineView.enterEditState(enterEditDuration);
        }
        currentState = HotSeatState.EDIT;
        editBtn.setSaveState();
        if (tipText.getVisibility() == View.VISIBLE)
            tipText.animate().alpha(0).setDuration(enterEditDuration);
        animType = ANIM_TYPE.EXPAND;
        initHeightStep(UIConfig.HotSeatMaxPageCount * UIConfig.hotSeatLineHeight);
        initYStep(0);
        LogUtils.d("ttt_anim", "++++++++++++++++++++++++++++++++++++++++++++");
        invalidate();

        // 消掉“点击‘添加’按钮进入编辑模式”的引导
        Tip readTip = GuideViewManager.getTipByKeyCode(KeyEvent.KEYCODE_ENTER,
                GuideTips.DESKTOP_TIPS);
        if (readTip != null)
            GuideViewManager.getInstance().readTip(readTip);
        GuideViewManager.getInstance().hideMe();

        showEditTips();
        if (pageNoImage.animate() != null)
            pageNoImage.animate().cancel();
        pageNoImage.animate().alpha(0).setDuration(100);
    }

    // 退出编辑状态
    public void exitEditState() {
        LogUtils.d("blur", "exit edit state");
        if (smallBg != null)
            setBackgroundDrawable(smallBg);
        handleItemKey = false;
        LogUtils.d("key", "-------enter edit status, set handleItemKey false");
        editBtn.requestFocus();
        focusLineIndex = findFirstValidLine();
        hideOrShowPageNoView();
        for (int i = 0; i < mainLayout.getChildCount(); i++) {
            HotSeatLine lineView = (HotSeatLine) mainLayout.getChildAt(i);
            lineView.exitEditState(enterEditDuration);
            if (i != focusLineIndex)
                lineView.setChildrenFocusable(false);
            else
                lineView.setChildrenFocusable(true);
        }
        currentState = HotSeatState.NORMAL;
        resetEditTipStatus();
        animType = ANIM_TYPE.SHRINK;
        initHeightStep(UIConfig.hotSeatLineHeight);
        initYStep(-focusLineIndex * UIConfig.hotSeatLineHeight);
        LogUtils.d("ttt_anim", "---------------------------------------------");
        invalidate();
        clickedChildPos = -1;

        // View focusedChild = mainLayout.getFocusedChild();
        // HotSeatLine crtLineView = null;
        // if(focusedChild != null)
        // {
        // crtLineView = (HotSeatLine) focusedChild;
        // focusLineIndex = crtLineView.getLineIndex();
        // }
        //
        // if(crtLineView == null || crtLineView.getAppItemCount() <= 0)
        // {
        // editBtn.requestFocus();
        // focusLineIndex = findFirstValidLine();
        // for(int i = 0; i < mainLayout.getChildCount(); i++)
        // {
        // HotSeatLine lineView = (HotSeatLine) mainLayout.getChildAt(i);
        // lineView.exitEditState(enterEditDuration);
        // if(i != focusLineIndex)
        // lineView.setChildrenFocusable(false);
        // else
        // lineView.setChildrenFocusable(true);
        // }
        // }
        // else{
        // int crtFocusPos = crtLineView.getFocusedChild().getId() %
        // UIConfig.HotSeatItemCountPerPage;
        // for(int i = 0; i < mainLayout.getChildCount(); i++)
        // {
        // HotSeatLine lineView = (HotSeatLine) mainLayout.getChildAt(i);
        // lineView.exitEditState(enterEditDuration);
        // if(i != focusLineIndex)
        // lineView.setChildrenFocusable(false);
        // else
        // lineView.setChildrenFocusable(true);
        // }
        // // skipMoveFocus = true;
        // crtLineView.setChildFocusPos(crtFocusPos);
        // int left = crtLineView.getFocusedChild().getLeft() + crtLineView.getLeft()
        // - UIConfig.focusBorderWidth;
        // int top = crtLineView.getFocusedChild().getTop() - UIConfig.focusBorderWidth;
        // int viewWidth = UIConfig.hotSeatItemWidth + 2 * UIConfig.focusBorderWidth;
        // int viewHeight = UIConfig.appItemHeight + 2 * UIConfig.focusBorderWidth;
        // moveFocus(left, top, viewWidth, viewHeight);
        // }
        // currentState = HotSeatState.NORMAL;
        // resetEditTipStatus();
        // animType = ANIM_TYPE.SHRINK;
        // initHeightStep(UIConfig.hotSeatLineHeight);
        // initYStep(-focusLineIndex * UIConfig.hotSeatLineHeight);
        // LogUtils.d("ttt_anim", "---------------------------------------------");
        // invalidate();
        // clickedChildPos = -1;

        // 消掉编辑模式下的引导
        for (Tip tip : GuideTips.EDIT_SAVE_TIPS) {
            GuideViewManager.getInstance().readTip(tip);
        }
        GuideViewManager.getInstance().hideMe();
        showHotSeatTips();
    }

    private void initHeightStep(int height) {
        destHeight = height;
        ViewGroup.LayoutParams params = this.getLayoutParams();
        if (destHeight == params.height) {
            stepHeight = 0;
            return;
        }
        stepHeight = (destHeight - params.height) / stepCount;
        if (stepHeight == 0) {
            if (destHeight - params.height > 0)
                stepHeight = 1;
            else
                stepHeight = -1;
        }
    }

    private void initYStep(int y) {
        destY = y;
        FrameLayout.LayoutParams params = (LayoutParams) mainLayout.getLayoutParams();
        if (destY == params.topMargin) {
            stepY = 0;
            return;
        }
        stepY = (destY - params.topMargin) / stepCount;
        if (stepY == 0) {
            if (destY > params.topMargin)
                stepY = 1;
            else
                stepY = -1;
        }
    }

    @Override
    protected void onDraw(Canvas canvas) {
        // TODO Auto-generated method stub
        if (animType == ANIM_TYPE.EXPAND || animType == ANIM_TYPE.SHRINK) {
            boolean yOK = false;
            boolean heightOK = false;
            FrameLayout.LayoutParams params = (LayoutParams) mainLayout.getLayoutParams();
            if (params.topMargin != destY) {
                if (Math.abs(destY - params.topMargin) <= Math.abs(stepY)) {
                    params.topMargin = destY;
                    yOK = true;
                } else
                    params.topMargin += stepY;
                mainLayout.setLayoutParams(params);
            } else
                yOK = true;

            ViewGroup.LayoutParams thisParams = this.getLayoutParams();
            if (thisParams.height != destHeight) {
                if (Math.abs(destHeight - thisParams.height) <= Math.abs(stepHeight)) {
                    thisParams.height = destHeight;
                    heightOK = true;
                } else
                    thisParams.height += stepHeight;
                this.setLayoutParams(thisParams);
            } else
                heightOK = true;

            if (heightOK && yOK) {
                if (animType == ANIM_TYPE.SHRINK) {
                    if (pageNoImage.animate() != null)
                        pageNoImage.animate().cancel();
                    pageNoImage.animate().alpha(1).y(pageNoMargin + focusLineIndex * scrollHeight)
                            .setDuration(100);
                }
                animType = ANIM_TYPE.NONE;
                handleItemKey = true;
                LogUtils.d("key", "shrink or expand finished, set handleItemKey true");
            }
            invalidate();
        } else if (animType == ANIM_TYPE.MOVE_NEXT || animType == ANIM_TYPE.MOVE_PREV) {
            FrameLayout.LayoutParams params = (LayoutParams) mainLayout.getLayoutParams();
            if (Math.abs(destY - params.topMargin) <= Math.abs(stepY)) {
                params.topMargin = destY;
                animType = ANIM_TYPE.NONE;
            } else
                params.topMargin += stepY;
            mainLayout.setLayoutParams(params);
            invalidate();
        }
        super.onDraw(canvas);
    }

    public void updateList(List<AppItemData> dataList) {
        if (dataList == null)
            itemCount = 0;
        else
            itemCount = dataList.size();

        if (itemCount > maxCount)
            itemCount = maxCount;
        int minPos = maxCount;
        for (int i = 0; i < itemCount; i++) {
            AppItemData data = dataList.get(i);
            AppItemView itemView = ItemViewFactory.createItemView(mContext, data);
            LayoutExtra extra = JObject.parseJObject(data.getLayoutExtra(), LayoutExtra.class);

            int pos = i;
            if (extra == null)
                Toast.makeText(mContext, "layoutExtra为空", Toast.LENGTH_LONG).show();
            else {
                pos = extra.getPosition();
                minPos = pos < minPos ? pos : minPos;
            }

            HotSeatLine line = layoutList.get(pos / UIConfig.HotSeatItemCountPerPage);
            line.addOrReplaceView(itemView, pos % UIConfig.HotSeatItemCountPerPage);
        }
        // 数据采集：每个快捷栏平均添加的应用数
        for (int i = 0; i < UIConfig.HotSeatMaxPageCount; i++) {
            HotSeatLine line = layoutList.get(i);
            LogAPIForAppStore.shortcutsCount(i, line.getAppItemCount());
        }
        // if(Thread.currentThread() != Looper.getMainLooper().getThread())
        // {
        // runOnUiThread(new Runnable()
        // {
        // @Override
        // public void run()
        // {
        // // TODO Auto-generated method stub
        // showArrowTip();
        // }
        // });
        // }
        // else
        // showArrowTip();
        // if(itemCount > 0)
        // {
        // doFocusAnim = false;
        // layoutList.get(minPos / UIConfig.HotSeatItemCountPerPage).
        // setChildFocusPos(minPos % UIConfig.HotSeatItemCountPerPage);
        // this.focusLineIndex = minPos / UIConfig.HotSeatItemCountPerPage;
        // LayoutParams mainParams = (LayoutParams) mainLayout.getLayoutParams();
        // mainParams.topMargin = -focusLineIndex * UIConfig.hotSeatLineHeight;
        // mainLayout.setLayoutParams(mainParams);
        // setCurrentLine(minPos / UIConfig.HotSeatItemCountPerPage);
        // editBtn.setEditState();
        // editBtn.setAlpha(0.1f);
        // LogUtils.d("yyy", "XXX item request focus");
        // }
        // else{
        // editBtn.requestFocus();
        // LogUtils.d("yyy", "editBtn request focus");
        // editBtn.setAddState();
        // tipText.setAlpha(1);
        // }
    }

    private void hideOrShowPageNoView() {
        int invilidLineNum = 0;
        for (int i = 0; i < UIConfig.HotSeatMaxPageCount; i++) {
            HotSeatLine lineView = layoutList.get(i);
            if (lineView.getAppItemCount() > 0)
                invilidLineNum++;
        }

        if (invilidLineNum > 1) {
            pageNoImage.setVisibility(View.VISIBLE);
        } else {
            pageNoImage.setVisibility(View.INVISIBLE);
        }
    }

    private int findFirstValidLine() {
        for (int i = 0; i < UIConfig.HotSeatMaxPageCount; i++) {
            HotSeatLine lineView = layoutList.get(i);
            if (lineView.getAppItemCount() > 0)
                return lineView.getLineIndex();

        }
        return 0;
    }

    private int findNextValidLineIndex(int startIndex) {
        for (int i = startIndex; i < UIConfig.HotSeatMaxPageCount; i++) {
            HotSeatLine lineView = layoutList.get(i);
            if (lineView.getAppItemCount() > 0)
                return lineView.getLineIndex();
        }
        return -1;
    }

    private int findPrevValidLineIndex(int startIndex) {
        for (int i = startIndex; i >= 0; i--) {
            HotSeatLine lineView = layoutList.get(i);
            if (lineView.getAppItemCount() > 0)
                return lineView.getLineIndex();
        }
        return -1;
    }

    private void setCurrentLine(int lineIndex) {
        this.focusLineIndex = lineIndex;
        for (int i = 0; i < UIConfig.HotSeatMaxPageCount; i++) {
            HotSeatLine lineView = layoutList.get(i);
            if (i == focusLineIndex)
                lineView.setChildrenFocusable(true);
            else
                lineView.setChildrenFocusable(false);
        }
        initYStep(-focusLineIndex * UIConfig.hotSeatLineHeight);
        animType = ANIM_TYPE.MOVE_NEXT;
        invalidate();
        resetPageScroll();
    }

    private boolean addItemReturn = false;
    private boolean bAddItemReturnChanged = false;

    public synchronized boolean addItem(final AppItemData data, final String path, final boolean binit) {
        Runnable run = new Runnable() {
            private void change(boolean val) {
                synchronized (this) {
                    addItemReturn = val;
                    bAddItemReturnChanged = true;
                    notify();
                }
            }

            @Override
            public void run() {
                if (data == null) {
                    change(false);
                    return;
                }
                LogUtils.d("add_item", "addItem, path = " + path + ", title = " + data.getTitle());
                if (path.equals(PathConstants.AddShortcutPath.INSTALL_APP.toString())) {
                    change(restoreLostItem(data));
                    return;
                }
                if (clickedChildPos != -1) // 此类情况为：进入编辑模式，通过PickActivity选择应用进行添加
                {
                    itemCount++;
                    LayoutExtra extra = JObject.parseJObject(data.getLayoutExtra(), LayoutExtra.class);
                    if (extra == null)
                        extra = new LayoutExtra();
                    extra.setPosition(clickedChildPos);
                    data.setLayoutExtra(extra.toString());

                    final int lineIndex = clickedChildPos / UIConfig.HotSeatItemCountPerPage;
                    final int pos = clickedChildPos % UIConfig.HotSeatItemCountPerPage;
                    // 提交添加应用至快捷栏的log
                    submitLogAddShortcut(lineIndex, pos, data,
                            PathConstants.AddShortcutPath.PICK_ACTIVITY.toString());
                    ((Activity) mContext).runOnUiThread(new Runnable() {
                        @Override
                        public void run() {
                            HotSeatLine layout = layoutList.get(lineIndex);
                            layout.addOrReplaceView(ItemViewFactory.createItemView(mContext, data), pos);
                            layout.setChildFocusPos(pos);
                        }
                    });
                    clickedChildPos = -1;
                    change(true);
                    return;
                } else { // 此类情况为：在全部应用界面，选择特定应用，打开菜单，点击“添加到首页”
                    for (int i = 0; i < UIConfig.HotSeatMaxPageCount; i++) {
                        HotSeatLine layout = layoutList.get(i);
                        int addPos = layout.getFirstAvailablePos();
                        if (addPos != -1) {
                            itemCount++;
                            if (!binit) {
                                LayoutExtra extra = JObject.parseJObject(data.getLayoutExtra(),
                                        LayoutExtra.class);
                                if (extra == null)
                                    extra = new LayoutExtra();
                                extra.setPosition(addPos);
                                data.setLayoutExtra(extra.toString());
                            } else {
                                LayoutExtra extra = JObject.parseJObject(data.getLayoutExtra(),
                                        LayoutExtra.class);
                                if (extra != null) {
                                    if (!extra.getPreseted())
                                        addPos = extra.getPosition();
                                    else {
                                        List<AppItemData> hotSeatList = NormalController.hostContext.getAllItems(false);
                                        for (AppItemData _data : hotSeatList) {
                                            try {
                                                if (_data.getMainActivity().equals(data.getMainActivity())) {
                                                    change(false);
                                                    return;
                                                }
                                            } catch (Exception e) {
                                            }
                                        }
                                        extra.setPosition(addPos);
                                        data.setLayoutExtra(extra.toJSONString());
                                    }
                                } else
                                    addPos = 0;
                            }
                            LogUtils.d("III", "add name:" + data.getTitle() + " pos:" + addPos);

                            final int lineIndex = i;
                            final int pos = addPos % UIConfig.HotSeatItemCountPerPage;
                            // 提交添加应用至快捷栏的log
                            submitLogAddShortcut(lineIndex, pos, data,
                                    PathConstants.AddShortcutPath.ALL_APPS_MENU.toString());
                            HotSeatLine layout1 = layoutList.get(lineIndex);
                            layout1.addOrReplaceView(ItemViewFactory.createItemView(mContext, data),
                                    pos);
                            hideOrShowPageNoView();
                            resetEditTipStatus();
                            change(true);
                            return;
                        }
                    }
                    change(false);
                    return;
                }
            }
        };
        addItemReturn = false;
        bAddItemReturnChanged = false;
        if (Looper.myLooper() == Looper.getMainLooper()) {
            run.run();
            return addItemReturn;
        } else {
            LiteHandlerThread.postOnUiThread(run);
            synchronized (run) {
                if (!bAddItemReturnChanged)
                    try {
                        run.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
            }
            return addItemReturn;
        }
    }

    public boolean removeItem(final AppItemData data, final String path) {
        if (data == null)
            return false;
        LogUtils.d("add_item", "removeItem, path = " + path + ", title = " + data.getTitle()
                + ", clickedChildPos = " + clickedChildPos);
        if (path.equals(PathConstants.RemoveShortcutPath.SHORTCUT_EDIT.toString())
                && clickedChildPos != -1) // 此类情况为：在编辑状态下，点击应用进行的移除操作
        {
            itemCount--;

            final int lineIndex = clickedChildPos / UIConfig.HotSeatItemCountPerPage;
            ((Activity) mContext).runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    // TODO Auto-generated method stub
                    HotSeatLine layout = layoutList.get(lineIndex);
                    layout.addOrReplaceView(new TempAddView(mContext), clickedChildPos
                            % UIConfig.HotSeatItemCountPerPage);
                    layout.setChildFocusPos(clickedChildPos % UIConfig.HotSeatItemCountPerPage);
                    // 提交从快捷栏移除应用的log
                    submitLogRemoveShortcut(clickedChildPos, data);
                }
            });
            return true;
        }
        if (path.equals(PathConstants.RemoveShortcutPath.UNINSTALL_APP.toString())) { // 此类情况为：在全部应用界面卸载了某个应用，则删除其在常用位对应的view
            itemCount--;
            LayoutExtra extra = JObject.parseJObject(data.getLayoutExtra(), LayoutExtra.class);
            final int pos = extra.getPosition();
            // 记下由于卸载而删掉的快捷栏应用，如果30s内接到同一应用的安装消息，则恢复该应用在快捷栏的位置
            markLostItem(data, pos);

            ((Activity) mContext).runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    // TODO Auto-generated method stub
                    HotSeatLine lineView = layoutList.get(pos / UIConfig.HotSeatItemCountPerPage);
                    View replacedChild = lineView.findViewById(pos);
                    if (replacedChild != null && replacedChild.hasFocus()) {
                        editBtn.requestFocus();
                        editBtn.setAlpha(1);
                    }
                    lineView.addOrReplaceView(new TempAddView(mContext), pos
                            % UIConfig.HotSeatItemCountPerPage);
                    resetEditTipStatus();
                    resetLine();
                }
            });
            return true;
        }
        if (path.equals(PathConstants.RemoveShortcutPath.UNPLUGIN_SDCARD.toString())) { // 此类情况为：sd卡存有添加至快捷栏上的应用，用户拔掉sd卡，则需要从快捷栏上删掉这些应用
            ((Activity) mContext).runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    // TODO Auto-generated method stub
                    itemCount--;
                    LayoutExtra extra = JObject.parseJObject(data.getLayoutExtra(),
                            LayoutExtra.class);
                    int pos = extra.getPosition();
                    HotSeatLine lineView = layoutList.get(pos / UIConfig.HotSeatItemCountPerPage);
                    View replacedChild = lineView.findViewById(pos);
                    if (replacedChild != null && replacedChild.hasFocus()) {
                        editBtn.requestFocus();
                        editBtn.setAlpha(1);
                    }
                    lineView.addOrReplaceView(new TempAddView(mContext), pos
                            % UIConfig.HotSeatItemCountPerPage);
                    resetEditTipStatus();
                    resetLine();
                }
            });
            return true;
        }
        return false;
    }

    public void markLostItem(AppItemData data, int pos) {
        lostItems.put(pos, data.getPackageName());
        Message msg = mainHandler.obtainMessage(UNINSTALL_TIMEOUT_MSG_ID);
        msg.arg1 = pos;
        msg.obj = data;
        mainHandler.sendMessageDelayed(msg, UNINSTALL_TIMEOUT_DURATION);
    }

    public boolean restoreLostItem(AppItemData data) {
        int foundKey = findIndexInLostItems(data);
        if (foundKey != -1) {
            itemCount++;
            addItemAtPos(foundKey, data);
            lostItems.remove(foundKey);
            return true;
        }
        return false;
    }

    private void addItemAtPos(int pos, final AppItemData data) {
        LayoutExtra extra = JObject.parseJObject(data.getLayoutExtra(), LayoutExtra.class);
        if (extra == null)
            extra = new LayoutExtra();
        extra.setPosition(pos);
        data.setLayoutExtra(extra.toString());

        final int lineIndex = pos / UIConfig.HotSeatItemCountPerPage;
        final int linePos = pos % UIConfig.HotSeatItemCountPerPage;
        // 提交添加应用至快捷栏的log
        submitLogAddShortcut(lineIndex, linePos, data,
                PathConstants.AddShortcutPath.PICK_ACTIVITY.toString());
        runOnUiThread(new Runnable() {
            @Override
            public void run() {
                // TODO Auto-generated method stub
                HotSeatLine layout = layoutList.get(lineIndex);
                layout.addOrReplaceView(ItemViewFactory.createItemView(mContext, data), linePos);
                resetEditTipStatus();
            }
        });
    }

    private int findIndexInLostItems(AppItemData data) {
        LogUtils.d("add_item", "  finding lost item, data pkg = " + data.getPackageName());
        for (int i = 0; i < lostItems.size(); i++) {
            int pos = lostItems.keyAt(i);
            String pkgName = lostItems.valueAt(i);
            LogUtils.d("add_item", "  --- " + i + ", pos = " + pos + ", pkgName = " + pkgName);
            if (pkgName.equals(data.getPackageName())) {
                return pos;
            }
        }
        return -1;
    }

    private void resetLine() {
        HotSeatLine line = layoutList.get(focusLineIndex);
        if (line.getAppItemCount() <= 0) {
            focusLineIndex = findFirstValidLine();
            hideOrShowPageNoView();
            setCurrentLine(focusLineIndex);
        }
    }

    // 由于应用更新时，首先要执行uninstall，然后才执行install
    // 而快捷栏只能收到removeItem和addItem消息，无法判别是应用更新还是常规的应用卸载，因此设置一个30s超时机制
    // A. 若卸载之后30s内收到同一应用的安装消息，则认为其为应用更新，则将应用置回原位，并且过程中不向后台提交添加和移除快捷栏的log
    // B. 则若卸载后30s仍未收到被卸载应用的安装消息，则认为其为常规卸载，这时才提交移除log，此后再收到该应用的安装消息也不会将其置回快捷栏原位置
    private static final int UNINSTALL_TIMEOUT_DURATION = 30000;
    private static final int UNINSTALL_TIMEOUT_MSG_ID = 1;
    private SparseArray<String> lostItems = new SparseArray<String>();
    private Handler mainHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            // TODO Auto-generated method stub
            if (msg.what == UNINSTALL_TIMEOUT_MSG_ID) {
                int pos = msg.arg1;
                AppItemData data = (AppItemData) msg.obj;
                int id = findIndexInLostItems(data);
                if (id != -1) {
                    lostItems.remove(id);
                    submitLogRemoveShortcut(pos, data);
                }
            }
            super.handleMessage(msg);
        }
    };

    // 数据采集：添加应用至快捷栏时统计，分为：1.在全部应用界面添加，2.通过PickActivity添加 两种path
    private void submitLogAddShortcut(final int row, final int column, final AppItemData data, final String path) {
        CoocaaApplication.post(new Runnable() {
            @Override
            public void run() {
                int appId = -1;
                try {

                    appId = Integer.valueOf(data.getId());
                } catch (Exception e) {
                }
                LogAPIForAppStore.shortcutsAdd(row, column, appId, data.getPackageName(), data.getTitle(),
                        path);
            }
        });
    }

    // 数据采集：从快捷栏移除应用时采集，分为：1.在快捷栏进入编辑模式移除；2.卸载应用移除 两种情况
    private void submitLogRemoveShortcut(int pos, AppItemData data) {
        int appId = -1;
        try {

            appId = Integer.valueOf(data.getId());
        } catch (Exception e) {
        }
        int row = pos / UIConfig.HotSeatItemCountPerPage;
        int column = pos % UIConfig.HotSeatItemCountPerPage;
        LogAPIForAppStore.shortcutsRemove(row, column, appId, data.getPackageName(),
                data.getTitle());
    }

    private HotSeatExecutor hotSeatExecutor;

    public void setHotSeatExecutor(HotSeatExecutor hotSeatExecutor) {
        this.hotSeatExecutor = hotSeatExecutor;
        for (HotSeatLine line : layoutList) {
            line.setHotSeatExecutor(hotSeatExecutor);
        }
    }

    private BoundaryDetector boundaryDetector;

    public void setBoundaryDetector(BoundaryDetector boundaryDetector) {
        this.boundaryDetector = boundaryDetector;
    }

    private ChildFocusListener childFocusListener = new ChildFocusListener() {
        @Override
        public void onChildFocusChange(Rect r) {
            // TODO Auto-generated method stub
            int viewWidth = r.right - r.left + 2 * UIConfig.focusBorderWidth;
            int viewHeight = r.bottom - r.top + 2 * UIConfig.focusBorderWidth;
            moveFocus(r.left - UIConfig.focusBorderWidth, r.top - UIConfig.focusBorderWidth,
                    viewWidth, viewHeight);
        }
    };

    private OnFocusChangeListener addEditFocusListener = new OnFocusChangeListener() {
        @Override
        public void onFocusChange(View v, boolean hasFocus) {
            // TODO Auto-generated method stub
            if (hasFocus) {
                if (v.getWidth() > 0 && v.getHeight() > 0) {
                    moveFocus(v.getLeft() - UIConfig.focusBorderWidth, v.getTop()
                            - UIConfig.focusBorderWidth, v.getWidth() + 2
                            * UIConfig.focusBorderWidth, v.getHeight() + 2
                            * UIConfig.focusBorderWidth);
                } else {
                    moveFocus(editLeftPadding - UIConfig.focusBorderWidth,
                            (UIConfig.hotSeatLineHeight - editAddSize) / 2
                                    - UIConfig.focusBorderWidth, editAddSize + 2
                                    * UIConfig.focusBorderWidth, editAddSize + 2
                                    * UIConfig.focusBorderWidth);
                }
            }
            if (currentState != HotSeatState.EDIT && itemCount > 0) {
                if (!hasFocus)
                    editBtn.animate().alpha(0.1f).setDuration(300);
                else
                    editBtn.animate().alpha(1).setDuration(300);
            }
        }
    };

    private void moveFocus(int left, int top, int width, int height) {
        if (doFocusAnim) {
            focusImage.changeFocusPos(left, top, width, height);
        } else {
            focusImage.setFocusPos(left, top, width, height);
        }
        doFocusAnim = true;
    }

    private int clickedChildPos = -1;
    private ChildClickListener childClickListener = new ChildClickListener() {
        @Override
        public void onChildClicked(int pos) {
            // TODO Auto-generated method stub
            HotSeatView.this.clickedChildPos = pos;
        }
    };

    @Override
    public boolean onKey(View v, int keyCode, KeyEvent event) {
        // TODO Auto-generated method stub
        LogUtils.d("key", "hot seat view - onkey");
        if (event.getAction() == KeyEvent.ACTION_DOWN) {
            if (processKeyDown(keyCode))
                return true;
        }
        return super.onKey(v, keyCode, event);
    }

    private boolean showNextLine(int pos) {
        if (focusLineIndex < UIConfig.HotSeatMaxPageCount) {
            int nextValidLineIndex = findNextValidLineIndex(focusLineIndex + 1);
            if (nextValidLineIndex >= 0) {
                setCurrentLine(nextValidLineIndex);
                if (pos != -1) {
                    layoutList.get(nextValidLineIndex).setChildFocusPos(pos);
                }
                return true;
            }
            return false;
        }
        return false;
    }

    private boolean showPrevLine(int pos) {
        if (focusLineIndex > 0) {
            int prevValidLineIndex = findPrevValidLineIndex(focusLineIndex - 1);
            if (prevValidLineIndex >= 0) {
                setCurrentLine(prevValidLineIndex);
                if (pos != -1)
                    layoutList.get(prevValidLineIndex).setChildFocusPos(pos);
                return true;
            }
            return false;
        }
        return false;
    }

    public boolean processKeyDown(int keyCode) {
        if (currentState == HotSeatState.EDIT) {
            if (keyCode == KeyEvent.KEYCODE_BACK) {
                exitEditState();
                return true;
            }
            if (keyCode == KeyEvent.KEYCODE_MENU)
                return true;
        } else {
            if (keyCode == KeyEvent.KEYCODE_DPAD_DOWN || keyCode == KeyEvent.KEYCODE_DPAD_UP) {
                markLastFocusView();
                int lastFocusPos = -1;
                if (lastFocusView != null)
                    lastFocusPos = lastFocusView.getId() % UIConfig.HotSeatItemCountPerPage;

                if (keyCode == KeyEvent.KEYCODE_DPAD_DOWN) {
                    if (!showNextLine(lastFocusPos)) // 如果没有找到下一个要显示的行，则需要展开全部我的应用
                    {
                        if (boundaryDetector != null) {
                            boundaryDetector.switchToAllApp();
                            // 消掉“按下键查看全部应用”的引导
                            Tip readTip = GuideViewManager.getTipByKeyCode(keyCode,
                                    GuideTips.DESKTOP_TIPS);
                            if (readTip != null)
                                GuideViewManager.getInstance().readTip(readTip);
                            GuideViewManager.getInstance().hideMe();
                            return true;
                        }
                    }
                    return true;
                } else {
                    showPrevLine(lastFocusPos);
                    return true;
                }
            }
        }
        return false;
    }

    public void markLastFocusView() {
        HotSeatLine lineView = (HotSeatLine) mainLayout.getChildAt(focusLineIndex);
        lastFocusView = lineView.getFocusedChild();
    }

    public void resetFocus() {
        if (lastFocusView != null && lastFocusView.getParent() != null)
            lastFocusView.requestFocus();
        else {
            editBtn.requestFocus();
            if (editBtn.getAlpha() != 1)
                editBtn.setAlpha(1);
        }
        HotSeatLine line = layoutList.get(focusLineIndex);
        if (line.getAppItemCount() <= 0) {
            focusLineIndex = findFirstValidLine();
            hideOrShowPageNoView();
            setCurrentLine(focusLineIndex);
        }
        showHotSeatTips();
    }

    public void initFocus() {
        if (itemCount > 0) {
            doFocusAnim = false;
            focusLineIndex = findFirstValidLine();
            hideOrShowPageNoView();
            layoutList.get(focusLineIndex).setChildFocusPos(0);
            LayoutParams mainParams = (LayoutParams) mainLayout.getLayoutParams();
            mainParams.topMargin = -focusLineIndex * UIConfig.hotSeatLineHeight;
            mainLayout.setLayoutParams(mainParams);
            setCurrentLine(focusLineIndex);
            editBtn.setEditState();
            editBtn.setAlpha(0.1f);
        } else {
            editBtn.requestFocus();
            editBtn.setAddState();
            tipText.setAlpha(1);
        }
        showArrowTip();
    }

    private ImageView downArrowImage;

    public void showArrowTip() {
        if (downArrowImage == null) {
            downArrowImage = new ImageView(mContext);
            SkinManager.getInstance().setBackgroundResource(downArrowImage,
                    R.drawable.hot_seat_down_arrow);
            this.addView(downArrowImage, new LayoutParams(LayoutParams.WRAP_CONTENT,
                    LayoutParams.WRAP_CONTENT, Gravity.BOTTOM | Gravity.CENTER_HORIZONTAL));
            downArrowImage.setAlpha(0);
        }
        PropertyValuesHolder alphaHolder = PropertyValuesHolder.ofFloat("alpha", 0, 1.0f, 0, 1.0f,
                0);
        ObjectAnimator anim = ObjectAnimator.ofPropertyValuesHolder(downArrowImage, alphaHolder);
        anim.setDuration(4000);
        anim.start();
    }

    public void setPickResultListener(PickResultListener listener) {
        for (HotSeatLine line : layoutList) {
            line.setPickResultListener(listener);
        }
    }

    private void showHotSeatTips() {
        GuideViewManager.getInstance().showMe(GuideTips.DESKTOP_TIPS,
                Gravity.CENTER_HORIZONTAL | Gravity.TOP, 0, SkyConstants.Div(40));
    }

    private void showEditTips() {
        GuideViewManager.getInstance().showMe(GuideTips.EDIT_SAVE_TIPS,
                Gravity.CENTER_HORIZONTAL | Gravity.TOP, 0, SkyConstants.Div(40));
    }

    private void recycleBitmapDrawable(BitmapDrawable drawable) {
        if (drawable != null && drawable.getBitmap() != null && !drawable.getBitmap().isRecycled()) {
            drawable.getBitmap().recycle();
        }
    }

    public void destory() {
        if(smallBg != null)
            recycleBitmapDrawable(smallBg);
        if(bigBg != null)
            recycleBitmapDrawable(bigBg);
        WallpaperManager.getInstance().removeBackgroundChangeListener(this);
    }
}
